package com.yunshipei.core.download.preview;

import android.content.Context;
import android.text.TextUtils;

import com.yunshipei.core.common.XCloudException;
import com.yunshipei.core.model.HttpAuthModel;
import com.yunshipei.core.net.DownloadApi;
import com.yunshipei.core.net.NTLMAuthenticator;
import com.yunshipei.core.utils.FileUtils;

import org.json.JSONArray;
import org.json.JSONObject;
import org.reactivestreams.Publisher;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import io.reactivex.Flowable;
import io.reactivex.functions.Function;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

class KingGridFileDownload {

    static final String FILE_STORAGE_PATH = "kingGridPath";
    private static final OkHttpClient.Builder downloadClientBuilder = new OkHttpClient.Builder().connectTimeout(20 * 60, TimeUnit.SECONDS).readTimeout(20 * 60, TimeUnit.SECONDS).writeTimeout(20 * 60, TimeUnit.SECONDS);

    private String downloadData = "";
    private String proxyIP = "";
    private int proxyPort = 0;

    private HttpAuthModel httpAuthModel;
    protected Context context;

    KingGridFileDownload(Context context, String downloadData, String proxyIP, int proxyPort, HttpAuthModel httpAuthModel) {
        this.context = context;
        this.httpAuthModel = httpAuthModel;
        this.downloadData = downloadData;
        this.proxyIP = proxyIP;
        this.proxyPort = proxyPort;
    }

    private String finalFileName = "";

    public Flowable<String> download() {
        return Flowable.just(true).flatMap(new Function<Boolean, Publisher<retrofit2.Response<ResponseBody>>>() {
            @Override
            public Publisher<retrofit2.Response<ResponseBody>> apply(Boolean aBoolean) throws Exception {
                JSONObject dataObject = new JSONObject(downloadData);
                //拼接请求参数
                String url = dataObject.optString("downloadUrl");
                finalFileName = dataObject.optString("docName", "") + dataObject.optString("docType", "");
                JSONArray jsonArray = dataObject.optJSONArray("downloadHttpParams");
                String requestParams = "";
                if (jsonArray != null) {
                    int len = jsonArray.length();
                    for (int i = 0; i < len; i++) {
                        JSONObject jsonObject = jsonArray.optJSONObject(i);
                        if (jsonObject != null) {
                            String key = jsonObject.optString("key");
                            String value = jsonObject.optString("value", "");
                            if (!TextUtils.isEmpty(key)) {
                                key = key.replaceAll("\\!\\@\\#\\$", " ");
                                requestParams += key + "=" + value + "\r\n";
                            }
                        }
                    }
                }
                RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), requestParams);
                //设置下载的cookie
                String cookie = "";
                JSONObject headerObjs = dataObject.optJSONObject("downloadHttpHeaders");
                if (headerObjs != null) {
                    cookie = headerObjs.optString("cookie", "");
                }
                if (!TextUtils.isEmpty(cookie)) {
                    final String finalCookie = cookie;
                    downloadClientBuilder.addInterceptor(new Interceptor() {
                        @Override
                        public Response intercept(Chain chain) throws IOException {
                            Request.Builder builder = chain.request().newBuilder();
                            builder.addHeader("Cookie", finalCookie);
                            return chain.proceed(builder.build());
                        }
                    });
                }
                //设置AD认证
                if (httpAuthModel != null) {
                    downloadClientBuilder.authenticator(new NTLMAuthenticator(httpAuthModel.getUserName(), httpAuthModel.getPassword()));
                }
                //设置下载的代理
                if (!TextUtils.isEmpty(proxyIP) && proxyPort > 0) {
                    SocketAddress sa = new InetSocketAddress(proxyIP, proxyPort);
                    //定义代理，此处的Proxy是源自java.net
                    Proxy proxy = new Proxy(Proxy.Type.HTTP, sa);
                    downloadClientBuilder.proxy(proxy);
                }
                OkHttpClient okHttpClient = downloadClientBuilder.build();
                DownloadApi serviceApi = new Retrofit.Builder().client(okHttpClient).baseUrl("http://127.0.0.1:8080").addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build().create(DownloadApi.class);
                return serviceApi.post(url, requestBody);
            }
        }).flatMap(new Function<retrofit2.Response<ResponseBody>, Publisher<String>>() {
            @Override
            public Publisher<String> apply(retrofit2.Response<ResponseBody> response) throws Exception {
                int code = response.code();
                if (code == 200) {
                    File file = new File(context.getFilesDir().getPath() + File.separator + FILE_STORAGE_PATH);
                    if (!file.exists() || !file.isDirectory()) {
                        boolean b = file.mkdirs();
                    }
                    String filePath = file.getPath();
                    String tempFileName = "temp_" + System.currentTimeMillis();
                    FileUtils.writeToFile(filePath, tempFileName, response.body().byteStream());
                    String content = FileUtils.readFile(filePath + File.separator + tempFileName);
                    String c64 = content.substring(0, 64);
                    Pattern p = Pattern.compile("\\s+(\\d*)\\s+(\\d*)\\s+(\\d*)\\s+");
                    Matcher matcher = p.matcher(c64);
                    int headerLength = 0;
                    int middleLength = 0;
                    int bodyLength = 0;
                    if (matcher.find()) {
                        headerLength = Integer.parseInt(matcher.group(1));
                        middleLength = Integer.parseInt(matcher.group(2));
                        bodyLength = Integer.parseInt(matcher.group(3));
                    } else {
                        return Flowable.error(new XCloudException("提取文件失败:" + code));
                    }
                    FileInputStream contentInputStream = new FileInputStream(filePath + File.separator + tempFileName);
                    long skip = contentInputStream.skip(headerLength + middleLength + 64);
                    int byteCount = bodyLength;
                    OutputStream outputStream = new FileOutputStream(filePath + File.separator + finalFileName);
                    byte[] bytes = new byte[byteCount];
                    int read = contentInputStream.read(bytes, 0, byteCount);
                    outputStream.write(bytes);
                    contentInputStream.close();
                    outputStream.close();
                    File tempFile = new File(filePath + File.separator + tempFileName);
                    boolean b = tempFile.delete();
                    return Flowable.just(filePath + File.separator + finalFileName);
                } else {
                    return Flowable.error(new XCloudException("下载失败,错误状态码:" + code));
                }
            }
        });
    }
}
